﻿using ISSMoviePlex.DAL.Models;
using ISSMoviePlex.DAL.Repositories;
using System.Collections.Generic;
using System.Transactions;
using System;

namespace ISSMoviePlex.BLL
{
    public class TicketBookingBLL
    {
        private readonly ScheduleRepository _schRepository;
        private readonly TicketRepository _tktRepository;
        private MemberBLL _memberLogic;

        public TicketBookingBLL()
        {
            _schRepository = ScheduleRepository.Instance;
            _schRepository.Initialize();
            _tktRepository = TicketRepository.Instance;
            _tktRepository.Initialize();
        }

        private void Validate(int noOfTicketsBooking, int scheduleId)
        {
            if (noOfTicketsBooking <= 0)
            {
                throw new Exception("Number of ticket must be greater than 0");
            }
            var seatsAvlbl = _schRepository.GetSeatsForSchedule(scheduleId);
            if (seatsAvlbl < noOfTicketsBooking)
            {
                throw new Exception("Number of ticket booking exceed number of seat available");
            }
        }

        public List<Ticket> PerformBooking(int noOfTicketsBooking, int scheduleId, int memberId, out double discount)
        {
            Validate(noOfTicketsBooking, scheduleId);
            using (var ts = new TransactionScope())
            {
                var tickets = new List<Ticket>();
                var sch = _schRepository.FindById(scheduleId);
                discount = 0;
                if (sch != null)
                {                    
                    DateTime bookingDate = DateTime.Now;
                    for (int i = 0; i < noOfTicketsBooking; i++)
                    {
                        var ticket = new Ticket
                        {
                            ScheduleId = scheduleId,
                            MemberId = memberId,
                            BookingDate = bookingDate,
                            SeatNo = (_tktRepository.GetSeatNo(scheduleId) + i + 1).ToString()
                        };
                        _tktRepository.Add(ticket);
                        tickets.Add(ticket);
                    }
                    sch.SeatAvailable -= noOfTicketsBooking;
                    _memberLogic = new MemberBLL(memberId);
                    discount = _memberLogic.Spend(noOfTicketsBooking * sch.TicketPrice);

                    _tktRepository.Save();
                    _schRepository.Save();
                }

                ts.Complete();
                return tickets;
            }
        }

        public double CalculatePrice(int noOfTicketsBooking, int memberId, int scheduleId)
        {
            double totalPrice = _schRepository.GetTotalPriceAfterDiscount(noOfTicketsBooking, scheduleId, memberId);
            return totalPrice;

        }

        public TicketDetailsViewModel PopulateTicketDetails(int ticketId)
        {
            TicketDetailsViewModel tcktDetlViewModel = _schRepository.PopulateTicketDetails(ticketId);
            return tcktDetlViewModel;
        }

        public List<TicketViewModel> PopulateTicketViewGrid(int movieId)
        {
            List<TicketViewModel> tvmList = _tktRepository.PopulateTicketViewGrid(movieId);
            return tvmList;
        }
    }
}
